home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / softwareproperties / MirrorTest.py < prev    next >
Encoding:
Python Source  |  2009-03-27  |  5.7 KB  |  149 lines

  1. #!/usr/bin/env python
  2. import threading, Queue, time, re, os, tempfile
  3. import aptsources
  4. from timeit import Timer
  5. import urllib
  6. import socket
  7. import random
  8.  
  9. # Python requires to set the time out globally
  10. socket.setdefaulttimeout(2)
  11.  
  12. class MirrorTest(threading.Thread):
  13.     """Determines the best mirrors by perfoming ping and download test."""
  14.     class PingWorker(threading.Thread):
  15.         """Use the command line command ping to determine the server's
  16.            response time. Using multiple threads allows to run several
  17.            test simultaneously."""
  18.         def __init__(self, jobs, results, id, parent, borders=(0,1), mod=(0,0)):
  19.             self.borders = borders
  20.             self.mod = mod
  21.             self.parent = parent
  22.             self.id = id
  23.             self.jobs = jobs
  24.             self.results = results
  25.             self.match_result = re.compile(r"^rtt .* = [\.\d]+/([\.\d]+)/.*")
  26.             threading.Thread.__init__(self)
  27.         def run(self):
  28.             result = None
  29.             while MirrorTest.completed < MirrorTest.todo and\
  30.                   self.parent.running.isSet():
  31.                 try:
  32.                     mirror = self.jobs.get(True, 1)
  33.                     host = mirror.hostname
  34.                 except:
  35.                     continue
  36.                 self.parent.report_action("Pinging %s..." % host)
  37.                 commando = os.popen("ping -q -c 2 -W 1 -i 0.5 %s" % host,
  38.                                     "r")
  39.                 while True:
  40.                     line = commando.readline()
  41.                     if not line:
  42.                         break
  43.                     result = re.findall(self.match_result, line)
  44.                 MirrorTest.completed_lock.acquire()
  45.                 MirrorTest.completed += 1
  46.                 self.parent.report_progress(MirrorTest.completed,
  47.                                             MirrorTest.todo,
  48.                                             self.borders,
  49.                                             self.mod)
  50.                 if result:
  51.                     self.results.append([float(result[0]), host, mirror])
  52.                 MirrorTest.completed_lock.release()
  53.  
  54.     def __init__(self, mirrors, test_file, running=None):
  55.         threading.Thread.__init__(self)
  56.         self.test_file = test_file
  57.         self.threads = []
  58.         MirrorTest.completed = 0
  59.         MirrorTest.completed_lock = threading.Lock()
  60.         MirrorTest.todo = len(mirrors)
  61.         self.mirrors = mirrors
  62.         if not running:
  63.             self.running = threading.Event()
  64.         else:
  65.             self.running = running
  66.  
  67.     def run_full_test(self):
  68.         """Run a test of the mirror test."""
  69.         results_ping = self.run_ping_test(max=10)
  70.         results = self.run_download_test(map(lambda r: r[2], results_ping))
  71.         for (t, h) in results:
  72.             print h.hostname,t
  73.  
  74.     def report_action(self, text):
  75.         """Should be used by all sub test to collect action status messages
  76.            in a central place."""
  77.         print text
  78.  
  79.     def report_progress(self, current, max, borders=(0,100), mod=(0,0)):
  80.         """Should be used by all sub test to collect progress messages
  81.            in a central place."""
  82.         print "Completed %s of %s" % (current + mod[0], max + mod[1])
  83.  
  84.     def run_ping_test(self, mirrors=None, max=None, borders=(0,1), mod=(0,0)):
  85.         """Performs ping tests of the given mirrors and returns the
  86.            best results (specified by max).
  87.            Mod and borders could be used to tweak the reported result if
  88.            the download test is only a part of a whole series of tests."""
  89.         if mirrors == None:
  90.             mirrors = self.mirrors
  91.         jobs = Queue.Queue()
  92.         for m in mirrors:
  93.             jobs.put(m)
  94.         results = []
  95.         #FIXME: Optimze the number of ping working threads LP#90379
  96.         for i in range(25):
  97.             t = MirrorTest.PingWorker(jobs, results, i, self, borders, mod)
  98.             self.threads.append(t)
  99.             t.start()
  100.  
  101.         for t in self.threads:
  102.             t.join()
  103.  
  104.         results.sort()
  105.         return results[0:max]
  106.  
  107.     def run_download_test(self, mirrors=None, max=None, borders=(0,1), 
  108.                           mod=(0,0)):
  109.         """Performs download tests of the given mirrors and returns the
  110.            best results (specified by max).
  111.            Mod and borders could be used to tweak the reported result if
  112.            the download test is only a part of a whole series of tests."""
  113.         def test_download_speed(mirror):
  114.             url = "%s/%s" % (mirror.get_repo_urls()[0],
  115.                              self.test_file)
  116.             self.report_action("Downloading %s..." % url)
  117.             start = time.time()
  118.             try:
  119.                 data = urllib.urlopen(url).read(102400)
  120.                 return time.time() - start
  121.             except:
  122.                 return 0
  123.         if mirrors == None:
  124.             mirrors = self.mirrors
  125.         results = []
  126.  
  127.         for m in mirrors:
  128.             if not self.running.isSet():
  129.                 break
  130.             download_time = test_download_speed(m)
  131.             if download_time > 0:
  132.                 results.append([download_time, m])
  133.             self.report_progress(mirrors.index(m), len(mirrors), (0.50,1), mod)
  134.         results.sort()
  135.         return results[0:max]
  136.  
  137. if __name__ == "__main__":
  138.     distro = aptsources.distro.get_distro()
  139.     distro.get_sources(aptsources.SourcesList())
  140.     pipe = os.popen("dpkg --print-architecture")
  141.     arch = pipe.read().strip()
  142.     test_file = "dists/%s/%s/binary-%s/Packages.gz" % \
  143.                 (distro.source_template.name,
  144.                  distro.source_template.components[0].name,
  145.                  arch)
  146.     app = MirrorTest(distro.source_template.mirror_set.values(),
  147.                      test_file)
  148.     app.run_full_test()
  149.